#include <extend.h>

extern BOOL bDebug;

void DebugN( LPSTR, LONG );
void Debug( LPSTR );

//----------------------------------------------------------------------------//

LPSTR chr( WORD w )
{
   LPSTR szChr = " ";

   szChr[ 0 ] = w;

   return szChr;
}

//----------------------------------------------------------------------------//

LPSTR ltrim( LPSTR szText )
{
   LPSTR szTemp = szText;

   while( * szTemp == ' ' )
      szTemp++;

   return szTemp;
}

//----------------------------------------------------------------------------//

LPSTR rtrim( LPSTR szText )
{
   WORD  wLen   = _strlen( szText );
   LPSTR szTemp = szText + wLen - 1;

   while( * szTemp == ' ' && szTemp > szText )
      szTemp--;

   * ++szTemp = 0;

   return szText;
}

//----------------------------------------------------------------------------//

void _strcpy( LPSTR cDest, LPSTR cSource )
{
   while( * cDest++ = * cSource++ );
}

//----------------------------------------------------------------------------//

void _strcat( LPSTR cDest, LPSTR cSource )
{
   WORD wLen = _strlen( cDest );

   while( * ( cDest + wLen++ ) = * cSource++ );
}

//----------------------------------------------------------------------------//

BOOL _strcmp( LPSTR sz1, LPSTR sz2 )
{
   while( * sz1 && * sz2 )
   {
      if( * sz1++ != * sz2++ )
         return FALSE;
   }

   if( * sz1 || * sz2 )
      return FALSE;

   return TRUE;
}

//----------------------------------------------------------------------------//

BOOL _strempty( LPSTR szText )
{
   LPSTR szTemp  = szText;
   BOOL bIsEmpty = TRUE;

   if( _strlen( szText ) )
      while( * szTemp && bIsEmpty )
         if( * szTemp++ != ' ' )
            bIsEmpty = FALSE;

   return bIsEmpty;
}

//----------------------------------------------------------------------------//

WORD _strgreater( LPSTR sz1, LPSTR sz2 )
{
   // Values returned 0 = equal, 1 = sz1 > sz2 , 2 = sz2 > sz1

   while( *( sz1 ) && *( sz2 ) && *( sz1 ) == *( sz2 ) )
   {
     sz1++;
     sz2++;
   }
   if ( ( *( sz1 ) == 0 && *( sz2 ) != 0 ) ||
        ( *( sz2 ) > *( sz1 ) )               )
      return 2;

   if ( ( *( sz1 ) != 0 && *( sz2 ) == 0 ) ||
        ( *( sz1 ) > *( sz2 ) )               )
      return 1;
   return 0;
}

//----------------------------------------------------------------------------//

WORD _strlen( LPSTR szText )
{
   WORD wLen = 0;

   while( * szText++ )
      wLen++;

   return wLen;
}

//----------------------------------------------------------------------------//

void SubStr( LPSTR pBuffer, LPSTR szText, WORD wStart, WORD wLen )
{
   WORD w;
   WORD wMaxLen = _strlen( szText );

   for( w = 0; w < wLen && w < wMaxLen; w++ )
      * pBuffer++ = * ( szText++ + wStart - 1 );
   * pBuffer = 0;
}

//----------------------------------------------------------------------------//

void _strupper( LPSTR szDest, LPSTR szOrg )
{
   while( * szOrg )
      if( ( * szOrg ) >= 'a' && ( * szOrg ) <= 'z' )
         * szDest++ = ( * szOrg++ ) - 'a' + 'A';
      else
         * szDest++ = * szOrg++;
   * szDest = 0;
}

//----------------------------------------------------------------------------//

void _strlower( LPSTR szDest, LPSTR szOrg )
{
   while( * szOrg )
      if( ( * szOrg ) >= 'A' && ( * szOrg ) <= 'Z' )
         * szDest++ = ( * szOrg++ ) - 'A' + 'a';
      else
         * szDest++ = * szOrg++;
   * szDest = 0;
}

//----------------------------------------------------------------------------//

void replicate( LPSTR pBuffer, LPSTR szText, WORD wTimes )
{
   WORD w;

   if( wTimes )
      _strcpy( pBuffer, szText );

   for( w = 1; w < wTimes; w++ )
      _strcat( pBuffer, szText );
}

//----------------------------------------------------------------------------//

void space( LPSTR pBuffer, WORD wLen )
{
   replicate( pBuffer, " ", wLen );
}

//----------------------------------------------------------------------------//

void _str( long lNumber, LPVOID pBuffer )
{
   BYTE szTemp[ 20 ];
   WORD w;
   BOOL bSigned = ( lNumber < 0 );

   for( w = 0; w < 19; szTemp[ w++ ] = ' ' );

   szTemp[ w ] = 0;

   if( bSigned )
      lNumber = -lNumber;

   do
   {
      szTemp[ --w ] = ( lNumber % 10 ) + '0';
      lNumber /= 10;
   } while( lNumber );

   if( bSigned )
      szTemp[ --w ] = '-';

   _strcpy( pBuffer, ( LPSTR ) szTemp + w );
}

//----------------------------------------------------------------------------//

void stuff( LPSTR str, LONG len, LONG pos, LONG del, LPSTR szInsert, LONG iLen )
{
   LONG  lTotalLen;
   LPSTR sResult;
   POVM  hResult;

   if( pos )
      pos--;

   if( pos > len )
      pos = len;

   if( del > len - pos )
      del = len - pos;

    if( ( lTotalLen = len + iLen - del ) > 0 )
	{
       if( ( hResult = _vmAlloc( lTotalLen + 1 ) ) &&
           ( sResult = _vmLock( hResult ) ) )
       {
          _bcopy( sResult, str, pos );
          _bcopy( sResult + pos, szInsert, iLen );
          _bcopy( sResult + pos + iLen, str + pos + del, len - ( pos + del ) );
          sResult[ lTotalLen ] = 0;

          _retclen( sResult, lTotalLen );
          _vmUnLock( hResult );
          _vmFree( hResult );
       }
	   else
          _retc( "" );
	}
	else
       _retc( "" );
}

//----------------------------------------------------------------------------//

CLIPPER STUFF()
{
   if( PCOUNT() == 4 && ISCHAR( 1 ) && ISNUM( 2 ) && ISNUM( 3 ) && ISCHAR( 4 ) )
   {
      stuff( _parc( 1 ), _parclen( 1 ), _parni( 2 ), _parni( 3 ), _parc( 4 ),
             _parclen( 4 ) );
   }
   else
      _retc( "" );
}

//----------------------------------------------------------------------------//

CLIPPER CHR()
{
   _retc( chr( _parni( 1 ) ) );
}

//----------------------------------------------------------------------------//

CLIPPER LTRIM()
{
   _retc( ltrim( _parc( 1 ) ) );
}

//----------------------------------------------------------------------------//

CLIPPER RTRIM()
{
   LPVOID pMem = _vmAlloc( _parclen( 1 ) + 1 );
   LPSTR  szTemp;

   _strcpy( szTemp = _vmLock( szTemp ), _parc( 1 ) );
   rtrim( szTemp );

   _retc( szTemp );
   _vmFree( pMem );
}

//----------------------------------------------------------------------------//

CLIPPER ALLTRIM()
{
   LPVOID pMem = _vmAlloc( _parclen( 1 ) + 1 );
   LPSTR  szTemp;

   _strcpy( szTemp = _vmLock( pMem ), _parc( 1 ) );
   rtrim( szTemp );

   _retc( ltrim( szTemp ) );
   _vmFree( pMem );
}

//----------------------------------------------------------------------------//

CLIPPER STR()
{
   BYTE buffer[ 20 ];
   long lValue = _parnl( 1 );

   if( -32768 <= lValue && lValue <= 32767 )
      _str( _parni( 1 ), buffer );
   else
      _str( lValue, buffer );

   _retc( buffer );
}

//----------------------------------------------------------------------------//

WORD _strat( LPSTR szToFind, LPSTR szText )
{
   WORD w1 = 0, w2 = 0, wAt = 0;
   BOOL bFound = FALSE;

   do
   {
      while( szText[ w1 ] && szText[ w1 ] != szToFind[ 0 ] )
         w1++;

      if( szText[ w1 ] )
      {
         w2  = 1;
         wAt = w1++;

         while( szText[ w1 ] && szToFind[ w2++ ] == szText[ w1++ ] );

         if( ! szText[ w1 ] )
            w2++;

         if( ! szToFind[ --w2 ] )
         {
            bFound = TRUE;
            wAt++;
         }
         else
         {
            w1  = wAt + 1;
            wAt = 0;
         }
      }

   } while( ! bFound && szText[ w1 ] );

   return wAt;
}

//----------------------------------------------------------------------------//

CLIPPER AT()
{
   _retni( _strat( _parc( 1 ), _parc( 2 ) ) );
}

//----------------------------------------------------------------------------//

CLIPPER REPLICATE()
{
   WORD wTimes  = _parni( 2 );
   LPVOID pVoid = _vmAlloc( ( _parclen( 1 ) * wTimes ) + 1 );
   LPSTR szText;

   replicate( szText = _vmLock( pVoid ), _parc( 1 ), wTimes );

   _retc( szText );
   _vmUnLock( pVoid );
   _vmFree( pVoid );
}

//----------------------------------------------------------------------------//

CLIPPER SPACE()
{
   WORD wLen    = _parni( 1 );
   LPVOID pVoid = _vmAlloc( wLen + 1 );
   LPSTR szText;

   space( szText = _vmLock( pVoid ), wLen );

   _retc( szText );
   _vmUnLock( pVoid );
   _vmFree( pVoid );
}

//----------------------------------------------------------------------------//

CLIPPER LEFT()
{
   _retclen( _parc( 1 ), _parni( 2 ) );
}

//----------------------------------------------------------------------------//

CLIPPER RIGHT()
{
   _retclen( _parc( 1 ) + _parclen( 1 ) - 3 - _parni( 2 ), _parni( 2 ) );
}

//----------------------------------------------------------------------------//

CLIPPER SUBSTR()
{
   WORD wFrom = _parni( 2 );
   WORD wLen  = _parni( 3 );

   if( ! wLen )
      wLen = _parclen( 1 ) - wFrom - 1;

   _retclen( _parc( 1 ) + IF( wFrom, wFrom - 1, wFrom ), wLen );
}

//----------------------------------------------------------------------------//

CLIPPER ASC()
{
   if( _pcount() && _ischar( 1 ) )
      _retni( * _parc( 1 ) );
   else
      _retni( 0 );
}

//----------------------------------------------------------------------------//

CLIPPER ISDIGIT()
{
   BYTE b;

   if( _pcount() && _ischar( 1 ) )
   {
      b = ( BYTE ) * _parc( 1 );
      _retl( ( '0' <= b ) && ( b <= '9' ) );
   }
   else
      _retl( FALSE );
}

//----------------------------------------------------------------------------//

CLIPPER LOWER()
{
   LPVOID pTemp = _vmAlloc( _parclen( 1 ) + 1 );
   LPSTR  szText;

   _strlower( szText = _vmLock( pTemp ), _parc( 1 ) );
   _retc( szText );
   _vmFree( pTemp );
}

//----------------------------------------------------------------------------//

CLIPPER UPPER()
{
   LPVOID pTemp = _vmAlloc( _parclen( 1 ) + 1 );
   LPSTR  szText;

   _strupper( szText = _vmLock( pTemp ), _parc( 1 ) );
   _retc( szText );
   _vmFree( pTemp );
}

//----------------------------------------------------------------------------//
